﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using ReportFramework.Common;
using ReportFramework.EntityFramework;

namespace ReportFramework.Common
{
    public class ReflectionHelper
    {
        public IList GetModelValue<T>(object entitiesObj, string entitiesPropertyName, int pageSize, int skip) where T : class
        {
            try
            {
                Type ts = entitiesObj.GetType();
                var query = (ts.GetProperty(entitiesPropertyName).GetValue(entitiesObj, null)) as DbSet<T>;
                if (query != null) return query.ToList();
                return null;
            }
            catch
            {
                return null;
            }
        }

        public static IList GetModelValue(object entitiesObj, string entitiesPropertyName, string retTypeName)
        {
            Type type = typeof(ReflectionHelper);
            object o = Activator.CreateInstance(type);
            Type type1 = Type.GetType(retTypeName);
            MethodInfo method = type.GetMethod("GetModelValue", BindingFlags.Instance | BindingFlags.Public);
            method = method.MakeGenericMethod(type1);
            return method.Invoke(o, new[] { entitiesObj, entitiesPropertyName}) as IList;
        }

        public Dictionary<string,object> GetFuncValue<T>(object entitiesObj, string entitiesFunName, int pageSize, int skip, Dictionary<string, string> vals) where T : class
        {
            try
            {
                Type ts = entitiesObj.GetType();
                MethodInfo methodInfo = ts.GetMethod(entitiesFunName);   
                ParameterInfo[] paramsInfo = methodInfo.GetParameters();//得到指定方法的参数列表 
                var len = paramsInfo.Length;
                var obj = new object[len];
                var i = 0;
                foreach (var param in paramsInfo)
                {
                    if (vals.ContainsKey(param.Name))
                    {
                        var tType = param.ParameterType;
                        var u = Nullable.GetUnderlyingType(tType);
                        if(tType.AssemblyQualifiedName != null && tType.AssemblyQualifiedName.Contains("System.Guid"))
                        {
                            obj[i] = Guid.Parse(vals[param.Name]);
                        }
                        else if (tType.AssemblyQualifiedName != null && (tType == typeof(string) || (!tType.IsInterface && !tType.IsClass)))
                        {
                            obj[i] = Convert.ChangeType(vals[param.Name], u ?? tType);
                        }
                        else if (tType.IsClass)//如果是类,将它的json字符串转换成对象   
                        {
                            obj[i] = Newtonsoft.Json.JsonConvert.DeserializeObject(vals[param.Name], u ?? tType);   
                        }
                    }
                    else
                    {
                        obj[i] = null;
                    }

                    i++;
                }
               
                 //执行方法   
                var query = methodInfo.Invoke(entitiesObj, obj) as ObjectResult<T>;
                var query1 = methodInfo.Invoke(entitiesObj, obj) as ObjectResult<T>;
                if (query != null && query1!=null)
                {
                    var data = query.Skip(skip).Take(pageSize).ToList();
                    var total = query1.Count();
                    return new Dictionary<string, object> {{"total", total}, {"data", data}};
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        public static Dictionary<string, object> GetFuncValue(object entitiesObj, string entitiesFunName, string retTypeName, int pageSize, int skip, Dictionary<string, string> vals)
        {
            Type type = typeof(ReflectionHelper);
            object o = Activator.CreateInstance(type);
            Type type1 = Type.GetType(retTypeName);
            MethodInfo method = type.GetMethod("GetFuncValue", BindingFlags.Instance | BindingFlags.Public);
            method = method.MakeGenericMethod(type1);
            return method.Invoke(o, new object[] { entitiesObj, entitiesFunName, pageSize, skip, vals }) as Dictionary<string, object>;
        }

        public Dictionary<string, object> CSqlQuery<T>(DbContext entitiesObj, string sql, int pageSize, int skip, params object[] parameters) where T : class
        {
            try
            {
                var query = entitiesObj.Database.SqlQuery<T>(sql, parameters);
                var parameters1 = (object[])parameters.Clone();
                var newSqlParameters = (from SqlParameter param in parameters select new SqlParameter(param.ParameterName, param.Value)).ToList();
                if (query != null)
                {
                    var data = query.Skip(skip).Take(pageSize).ToList();
                    var query1 = entitiesObj.Database.SqlQuery<T>(sql, newSqlParameters.ToArray());
                    var total = query1.Count();
                    return new Dictionary<string, object> { { "total", total }, { "data", data } };
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        public static Dictionary<string, object> CSqlQuery(DbContext entitiesObj, string retTypeName, string sql, int pageSize, int skip, params SqlParameter[] parameters)
        {
            try
            {
                Type type = typeof(ReflectionHelper);
                object o = Activator.CreateInstance(type);
                Type type1 = Type.GetType(retTypeName);
                MethodInfo methodInfo = type.GetMethod("CSqlQuery", BindingFlags.Instance | BindingFlags.Public);
                methodInfo = methodInfo.MakeGenericMethod(type1);
                var queryData = methodInfo.Invoke(o, new object[] { entitiesObj, sql, pageSize, skip, parameters }) as Dictionary<string, object>;

                return queryData;
            }
            catch
            {
                return null;
            }
        }

        //重载上面所有函数 for Return all data
        public Dictionary<string, object> GetFuncValueAll<T>(object entitiesObj, string entitiesFunName, Dictionary<string, string> vals) where T : class
        {
            try
            {
                Type ts = entitiesObj.GetType();
                MethodInfo methodInfo = ts.GetMethod(entitiesFunName);
                ParameterInfo[] paramsInfo = methodInfo.GetParameters();//得到指定方法的参数列表 
                var len = paramsInfo.Length;
                var obj = new object[len];
                var i = 0;
                foreach (var param in paramsInfo)
                {
                    if (vals.ContainsKey(param.Name))
                    {
                        var tType = param.ParameterType;
                        var u = Nullable.GetUnderlyingType(tType);
                        if (tType.AssemblyQualifiedName != null && tType.AssemblyQualifiedName.Contains("System.Guid"))
                        {
                            obj[i] = Guid.Parse(vals[param.Name]);
                        }
                        else if (tType.AssemblyQualifiedName != null && (tType == typeof(string) || (!tType.IsInterface && !tType.IsClass)))
                        {
                            obj[i] = Convert.ChangeType(vals[param.Name], u ?? tType);
                        }
                        else if (tType.IsClass)//如果是类,将它的json字符串转换成对象   
                        {
                            obj[i] = Newtonsoft.Json.JsonConvert.DeserializeObject(vals[param.Name], u ?? tType);
                        }
                    }
                    else
                    {
                        obj[i] = null;
                    }

                    i++;
                }

                //执行方法   
                var query = methodInfo.Invoke(entitiesObj, obj) as ObjectResult<T>;
                if (query != null)
                {
                    var data = query.ToList();
                    return new Dictionary<string, object> { { "data", data } };
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        public static Dictionary<string, object> GetFuncValueAll(object entitiesObj, string entitiesFunName, string retTypeName, Dictionary<string, string> vals)
        {
            Type type = typeof(ReflectionHelper);
            object o = Activator.CreateInstance(type);
            Type type1 = Type.GetType(retTypeName);
            MethodInfo method = type.GetMethod("GetFuncValueAll", BindingFlags.Instance | BindingFlags.Public);
            method = method.MakeGenericMethod(type1);
            return method.Invoke(o, new object[] { entitiesObj, entitiesFunName, vals }) as Dictionary<string, object>;
        }

        public Dictionary<string, object> CSqlQueryAll<T>(DbContext entitiesObj, string sql, params object[] parameters) where T : class
        {
            try
            {
                var query = entitiesObj.Database.SqlQuery<T>(sql, parameters);
                var parameters1 = (object[])parameters.Clone();
                if (query != null)
                {
                    var data = query.ToList();
                    return new Dictionary<string, object> { { "data", data } };
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        public static Dictionary<string, object> CSqlQueryAll(DbContext entitiesObj, string retTypeName, string sql, params SqlParameter[] parameters)
        {
            try
            {
                Type type = typeof(ReflectionHelper);
                object o = Activator.CreateInstance(type);
                Type type1 = Type.GetType(retTypeName);
                MethodInfo methodInfo = type.GetMethod("CSqlQueryAll", BindingFlags.Instance | BindingFlags.Public);
                methodInfo = methodInfo.MakeGenericMethod(type1);
                var queryData = methodInfo.Invoke(o, new object[] { entitiesObj, sql, parameters }) as Dictionary<string, object>;

                return queryData;
            }
            catch
            {
                return null;
            }
        }
    }
}